package logic

import (
	"GoWebBluebell/dao/mysql"
	"GoWebBluebell/dao/redis"
	"GoWebBluebell/models"
	"GoWebBluebell/pkg/snowflake"

	"go.uber.org/zap"
)

func CreatePost(p *models.Post) (err error) {
	// 1.生成post id
	p.ID = snowflake.GenID()

	// 2.保存到数据库 返回结果
	err = mysql.CreatePost(p)
	if err != nil {
		return err
	}
	//将创建时间记录到redis里(投票时用)
	err = redis.CreatePost(p.ID, p.CommunityID)
	if err != nil {
		return err
	}
	return err
}

// GetPostByID 根据帖子id查询帖子详情数据
func GetPostByID(pid int64) (data *models.ApiPostDetail, err error) {
	// 查询并拼接组合接口想用的数据

	post, err := mysql.GetPostByID(pid)
	if err != nil {
		zap.L().Error("mysql.GetPostByID(pid) failed", zap.Error(err))
		return
	}
	//根据作者id查询作者信息
	user, err := mysql.GetUserByID(post.AuthorID)
	if err != nil {
		zap.L().Error("mysql.GetUserByID(post.AuthorID) failed", zap.Error(err))
		return
	}
	//根据社区id查询社区详细信息
	community, err := mysql.GetCommunityDetailByID(post.CommunityID)
	if err != nil {
		zap.L().Error("mysql.GETCommunityDetailByID(post.CommunityID) failed", zap.Error(err))
		return
	}

	data = &models.ApiPostDetail{
		AuthorName:      user.Username,
		Post:            post,
		CommunityDetail: community,
	}
	return
}

// GetPostList 获取帖子列表
func GetPostList(page, size int64) (data []*models.ApiPostDetail, err error) {
	posts, err := mysql.GetPostList(page, size)
	if err != nil {
		return nil, err
	}
	data = make([]*models.ApiPostDetail, 0, len(posts))

	for _, post := range posts {
		//根据作者id查询作者信息
		user, err := mysql.GetUserByID(post.AuthorID)
		if err != nil {
			zap.L().Error("mysql.GetUserByID(post.AuthorID) failed",
				zap.Int64("author_id", post.AuthorID), zap.Error(err))
			continue
		}
		//根据社区id查询社区详细信息
		community, err := mysql.GetCommunityDetailByID(post.CommunityID)
		if err != nil {
			zap.L().Error("mysql.GETCommunityDetailByID(post.CommunityID) failed", zap.Error(err))
			continue
		}
		postDetail := &models.ApiPostDetail{
			AuthorName:      user.Username,
			Post:            post,
			CommunityDetail: community,
		}
		data = append(data, postDetail)
	}
	return
}

func GetPostList2(p *models.ParamPostList) (data []*models.ApiPostDetail, err error) {
	// 2. 去redis查询id列表
	pids, err := redis.GetPostIDsInOrder(p)
	if err != nil {
		return
	}
	if len(pids) == 0 {
		zap.L().Warn("redis GetPostIDsInOrder(p) return 0 data")
		return
	}
	// 3. 根据id去mysql查询帖子详细信息
	// 返回的数据要按照我给定的id的顺序返回(order by FIND_IN_SET 或者查询完手动排序)
	posts, err := mysql.GetPostListByIDs(pids)
	if err != nil {
		return
	}

	// 提前查好每篇帖子的投票数
	voteData, err := redis.GetPostVoteData(pids)
	if err != nil {
		return
	}

	//将帖子的作者及分区信息查询出来填充
	for idx, post := range posts {
		//根据作者id查询作者信息
		user, err := mysql.GetUserByID(post.AuthorID)
		if err != nil {
			zap.L().Error("mysql.GetUserByID(post.AuthorID) failed",
				zap.Int64("author_id", post.AuthorID), zap.Error(err))
			continue
		}
		//根据社区id查询社区详细信息
		community, err := mysql.GetCommunityDetailByID(post.CommunityID)
		if err != nil {
			zap.L().Error("mysql.GETCommunityDetailByID(post.CommunityID) failed", zap.Error(err))
			continue
		}
		postDetail := &models.ApiPostDetail{
			AuthorName:      user.Username,
			VoteNum:         voteData[idx],
			Post:            post,
			CommunityDetail: community,
		}
		data = append(data, postDetail)
	}
	return
}

func GetCommunityPostList(p *models.ParamPostList) (data []*models.ApiPostDetail, err error) {
	// 2. 去redis查询id列表
	pids, err := redis.GetCommunityPostIDsInOrder(p)
	if err != nil {
		return
	}
	if len(pids) == 0 {
		zap.L().Warn("redis GetCommunityPostIDsInOrder(p) return 0 data")
		return
	}
	// 3. 根据id去mysql查询帖子详细信息
	// 返回的数据要按照我给定的id的顺序返回(order by FIND_IN_SET 或者查询完手动排序)
	posts, err := mysql.GetPostListByIDs(pids)
	if err != nil {
		return
	}

	// 提前查好每篇帖子的投票数
	voteData, err := redis.GetPostVoteData(pids)
	if err != nil {
		return
	}

	//将帖子的作者及分区信息查询出来填充
	for idx, post := range posts {
		//根据作者id查询作者信息
		user, err := mysql.GetUserByID(post.AuthorID)
		if err != nil {
			zap.L().Error("mysql.GetUserByID(post.AuthorID) failed",
				zap.Int64("author_id", post.AuthorID), zap.Error(err))
			continue
		}
		//根据社区id查询社区详细信息
		community, err := mysql.GetCommunityDetailByID(post.CommunityID)
		if err != nil {
			zap.L().Error("mysql.GETCommunityDetailByID(post.CommunityID) failed", zap.Error(err))
			continue
		}
		postDetail := &models.ApiPostDetail{
			AuthorName:      user.Username,
			VoteNum:         voteData[idx],
			Post:            post,
			CommunityDetail: community,
		}
		data = append(data, postDetail)
	}
	return
}

// GetPostListNew 将两个查询逻辑合二为一的函数
func GetPostListNew(p *models.ParamPostList) (data []*models.ApiPostDetail, err error) {
	if p.CommunityID == 0 {
		//查所有
		data, err = GetPostList2(p)
	} else {
		data, err = GetCommunityPostList(p)
	}
	if err != nil {
		zap.L().Error("GetPostListNew failed", zap.Error(err))
		return nil, err
	}
	return
}
